package com.biz.primus.app.erpbridge.service;

import com.biz.primus.base.enums.commodity.OssType;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.google.common.collect.Lists.newArrayList;

/**
 * OssFullDataHandler
 *
 * @author JKLiues
 * @date 2017年11月17日
 */
@Slf4j
public abstract class OssFullDataHandler {

    private static final int PIPELINE_COUNT = 1000;

    protected OssType type;

    public abstract OssType[] getOssType();

    public int process(File file, OssType type) {
        this.type = type;
        log.debug("处理全量{}前置操作开始.", type.getDescription());
        this.preHandle(type);
        log.debug("处理全量{}前置操作完成.", type.getDescription());
        log.debug("处理全量{}操作开始. ", type.getDescription());
        this.handle(file);
        log.debug("处理全量{}操作完成. ", type.getDescription());
        log.debug("处理全量{}后置操作开始.", type.getDescription());
        this.afterHandle(type);
        log.debug("处理全量{}后置操作完成.", type.getDescription());
        return 0;
    }

    private void handle(File file) {
        Stopwatch stopwatch = Stopwatch.createStarted();
        InputStreamReader inStreamReader = null;
        BufferedReader reader = null;
        int count = 0;
        int finishedCount = 0;
        try {
            inStreamReader = new InputStreamReader(new FileInputStream(file), "UTF-8");
            reader = new BufferedReader(inStreamReader);
            //循环，每次读一行

            String line;
            List<String> jsons = newArrayList();
            while ((line = reader.readLine()) != null) {
                try {
                    log.debug("处理全量{}: {}, line: {}", type.getDescription(), line, ++count);
                    jsons.add(StringUtils.remove(line, "\\\\\""));
                    if (jsons.size() == PIPELINE_COUNT) {
                        finishedCount += this.handleData(jsons);
                        log.debug("全量{}处理进度. 完成: {}, 总计: {}", type.getDescription(), finishedCount, count);
                        jsons.clear();
                    }
                } catch (Exception e) {
                    log.error("处理全量{}异常: {}, 完成: {}, 总计: {}", type.getDescription(), line, finishedCount, count, e);
                }
            }
            if (CollectionUtils.isNotEmpty(jsons)) {
                finishedCount += this.handleData(jsons);
                log.debug("全量{}处理进度. 完成: {}, 总计: {}", type.getDescription(), finishedCount, count);
            }
        } catch (IOException e) {
            log.error("处理全量{}异常. 完成: {}, 总计: {} ", type.getDescription(), finishedCount, count, e);
        } finally {
            try {
                if (reader != null)
                    reader.close();
            } catch (IOException ignored) {
            }
            try {
                if (inStreamReader != null)
                    inStreamReader.close();
            } catch (IOException ignored) {
            }
        }
        log.debug("处理全量{}完成. 用时 {} ms, 完成数量: {}, 总计: {}", type.getDescription(), stopwatch.elapsed(TimeUnit
                .MILLISECONDS), finishedCount, count);
    }

    protected abstract void preHandle(OssType type);

    protected abstract int handleData(List<String> jsons);

    protected abstract void afterHandle(OssType type);

}